/* Turska Framework/UI library (Turs2)
 * Copyright 2003-2009 Jetro Lauha
 * All rights reserved.
 * Web: http://iki.fi/jetro/turska/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of EITHER:
 *   (1) The GNU Lesser General Public License as published by the Free
 *       Software Foundation; either version 2.1 of the License, or (at
 *       your option) any later version. The text of the GNU Lesser
 *       General Public License is included with this library in the
 *       file LICENSE-LGPL.txt.
 *   (2) The BSD-style license that is included with this library in
 *       the file LICENSE-BSD.txt.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
 * LICENSE-LGPL.txt and LICENSE-BSD.txt for more details.
 *
 * $Id: T2IMGUIImageSliderStyle.cpp 131 2009-06-05 05:58:05Z jlauha $
 * $Revision: 131 $
 */

#include <assert.h>

#include "Turs2.h"


namespace turska
{


IMGUIImageSliderStyle::IMGUIImageSliderStyle(Image *imageDefault, Image *imageHot,
                                             Image *imageActive, Image *imageHotActive,
                                             Image *thumbImageDefault, Image *thumbImageHot,
                                             Image *thumbImageActive, Image *thumbImageHotActive) :
    mScale(1),
    mImageWidth(30), mImageHeight(8),
    mThumbImageWidth(3), mThumbImageHeight(4),
    mKeyFocusAllowed(true)
{
    mSliderColor.set(0xffffffff);
    mThumbColor.set(0xffffffff);
    mSliderImages[IMGUI_WS_DEFAULT] = imageDefault;
    mSliderImages[IMGUI_WS_HOT] = imageHot;
    mSliderImages[IMGUI_WS_ACTIVE] = imageActive;
    mSliderImages[IMGUI_WS_HOT_ACTIVE] = imageHotActive;
    mThumbImages[IMGUI_WS_DEFAULT] = thumbImageDefault;
    mThumbImages[IMGUI_WS_HOT] = thumbImageHot;
    mThumbImages[IMGUI_WS_ACTIVE] = thumbImageActive;
    mThumbImages[IMGUI_WS_HOT_ACTIVE] = thumbImageHotActive;

    Image *img = mSliderImages[IMGUI_WS_DEFAULT];
    if (img == 0)
        img = mSliderImages[IMGUI_WS_HOT];
    if (img == 0)
        img = mSliderImages[IMGUI_WS_ACTIVE];
    if (img == 0)
        img = mSliderImages[IMGUI_WS_HOT_ACTIVE];
    if (img != 0)
    {
        mImageWidth = (UI32)img->getWidth();
        mImageHeight = (UI32)img->getHeight();
    }

    img = mThumbImages[IMGUI_WS_DEFAULT];
    if (img == 0)
        img = mThumbImages[IMGUI_WS_HOT];
    if (img == 0)
        img = mThumbImages[IMGUI_WS_ACTIVE];
    if (img == 0)
        img = mThumbImages[IMGUI_WS_HOT_ACTIVE];
    if (img != 0)
    {
        mThumbImageWidth = (UI32)img->getWidth();
        mThumbImageHeight = (UI32)img->getHeight();
    }
}


bool IMGUIImageSliderStyle::isInside(const IMGUI &imgui, REAL x, REAL y, const Rectangle &area)
{
    if (mSliderImages[IMGUI_WS_DEFAULT] != 0)
    {
        Rectangle r(area.x, area.y, mImageWidth * mScale, mImageHeight * mScale);
        return r.isInside(x, y);
    }
    else
        return area.isInside(x, y);
}


void IMGUIImageSliderStyle::getIntModifierMultipliers(I32 &shift, I32 &control)
{
    shift = 5;
    control = 20;
}


void IMGUIImageSliderStyle::getRealModifierMultipliers(REAL &shift, REAL &control)
{
    shift = 5;
    control = 20;
}


I32 IMGUIImageSliderStyle::getIntValue(const IMGUI &imgui, IMGUI_WIDGET_ORIENTATION axis,
                                       I32 minValue, I32 maxValue,
                                       REAL x, REAL y, const Rectangle &orgArea)
{
    Rectangle area = orgArea;
    assert(axis == IMGUI_WO_HORIZONTAL || axis == IMGUI_WO_VERTICAL);
    I32 pos, length;
    REAL thumbWidth = (REAL)mThumbImageWidth, thumbHeight = (REAL)mThumbImageHeight;
    if (mSliderImages[IMGUI_WS_DEFAULT] != 0)
    {
        area.width = mImageWidth * mScale;
        area.height = mImageHeight * mScale;
        thumbWidth = mThumbImageWidth * mScale;
        thumbHeight = mThumbImageHeight * mScale;
    }

    if (axis == IMGUI_WO_VERTICAL)
    {
        pos = (I32)(y - area.y - thumbHeight / 2);
        length = (I32)(area.height - thumbHeight);
    }
    else
    {
        // default to horizontal
        pos = (I32)(x - area.x - thumbWidth / 2);
        length = (I32)(area.width - thumbWidth);
    }
    if (length == 0)
        length = 1;

    I32 fpQ = 0;
    I32 toValueRange = maxValue - minValue + 1;
    if (toValueRange < 256)
    {
        // use Q8 fixed point for small value ranges
        // to get better rounding precision
        fpQ = 8;
        toValueRange <<= fpQ;
    }
    I32 fromRangeRound = toValueRange >> 1;
    I32 result = (pos * toValueRange + fromRangeRound) / length;
    result >>= fpQ;

    result += minValue;

    if (result < minValue)
        result = minValue;
    if (result > maxValue)
        result = maxValue;

    return result;
}


REAL IMGUIImageSliderStyle::getRealValue(const IMGUI &imgui, IMGUI_WIDGET_ORIENTATION axis,
                                         REAL minValue, REAL maxValue,
                                         REAL x, REAL y, const Rectangle &orgArea)
{
    Rectangle area = orgArea;
    assert(axis == IMGUI_WO_HORIZONTAL || axis == IMGUI_WO_VERTICAL);
    REAL pos, length;
    REAL thumbWidth = (REAL)mThumbImageWidth, thumbHeight = (REAL)mThumbImageHeight;
    if (mSliderImages[IMGUI_WS_DEFAULT] != 0)
    {
        area.width = mImageWidth * mScale;
        area.height = mImageHeight * mScale;
        thumbWidth = mThumbImageWidth * mScale;
        thumbHeight = mThumbImageHeight * mScale;
    }

    if (axis == IMGUI_WO_VERTICAL)
    {
        pos = y - area.y - thumbHeight / 2;
        if (pos < 0) pos = 0;
        length = area.height - thumbHeight;
        if (pos > length) pos = length;
    }
    else
    {
        // default to horizontal
        pos = x - area.x - thumbWidth / 2;
        length = area.width - thumbWidth;
    }
    if (length == 0)
        length = 1;

    REAL toValueRange = maxValue - minValue;
    REAL result = (pos * toValueRange) / length;
    result += minValue;

    if (result < minValue)
        result = minValue;
    if (result > maxValue)
        result = maxValue;

    return result;
}


Rectangle IMGUIImageSliderStyle::render(const IMGUI &imgui, I32 widgetState, IMGUI_WIDGET_ORIENTATION axis,
                                        I32 value, I32 minValue, I32 maxValue,
                                        REAL x, REAL y, REAL width, REAL height)
{
    REAL normalizedValue;

    const REAL fromRange = (REAL)(maxValue - minValue);
    normalizedValue = (value - minValue) / fromRange;

    return render(imgui, widgetState, axis, normalizedValue, x, y, width, height);
}


Rectangle IMGUIImageSliderStyle::render(const IMGUI &imgui, I32 widgetState, IMGUI_WIDGET_ORIENTATION axis,
                                        REAL value, REAL minValue, REAL maxValue,
                                        REAL x, REAL y, REAL width, REAL height)
{
    REAL normalizedValue;

    const REAL fromRange = maxValue - minValue;
    normalizedValue = (value - minValue) / fromRange;

    return render(imgui, widgetState, axis, normalizedValue, x, y, width, height);
}


Rectangle IMGUIImageSliderStyle::render(const IMGUI &imgui, I32 widgetState, IMGUI_WIDGET_ORIENTATION axis,
                                        REAL normalizedValue,
                                        REAL x, REAL y, REAL width, REAL height)
{
    assert(widgetState >= 0 && widgetState < IMGUI_WS_COUNT);
    const bool renderingEnabled = imgui.isRenderingEnabled();
    Image *sliderImage = mSliderImages[widgetState];
    UI32 defaultFlags = IF_TRANSFORM | IF_SCALE | IF_COLOR | IF_ALPHA;
    REAL thumbWidth = (REAL)mThumbImageWidth, thumbHeight = (REAL)mThumbImageHeight;
    x = (REAL)((I32)x);
    y = (REAL)((I32)y);
    if (sliderImage != 0)
    {
        if (renderingEnabled)
        {
            sliderImage->setScale(mScale);
            sliderImage->draw(IDM_NORMAL, defaultFlags, x, y, mSliderColor);
        }
        width = mImageWidth * mScale;
        height = mImageHeight * mScale;
        thumbWidth = mThumbImageWidth * mScale;
        thumbHeight = mThumbImageHeight * mScale;
    }
    Rectangle resultArea(x, y, width, height);

    REAL thumbX = x, thumbY = y;
    if (axis == IMGUI_WO_VERTICAL)
    {
        REAL toRange = height - thumbHeight;
        thumbX += width / 2;
        thumbY += normalizedValue * toRange + thumbHeight / 2;
    }
    else
    {
        // default to horizontal
        REAL toRange = width - thumbWidth;
        thumbX += normalizedValue * toRange + thumbWidth / 2;
        thumbY += height / 2;
    }

    thumbX = (REAL)((I32)thumbX);
    thumbY = (REAL)((I32)thumbY);

    // thumb
    Image *thumbImage = mThumbImages[widgetState];
    if (renderingEnabled && thumbImage != 0)
    {
        thumbImage->setScale(mScale);
        thumbImage->draw(IDM_NORMAL, defaultFlags | IF_ALIGN_CENTER,
                         thumbX, thumbY, mThumbColor);
    }

    return resultArea;
}


} // namespace turska
